/*
 * The contents of this web application are subject to the Mozilla Public License Version 
 * 1.1 (the "License"); you may not use this web application except in compliance with 
 * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, 
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
 * for the specific language governing rights and limitations under the License.
 * 
 * The Original Code is owned by and the Initial Developer of the Original Code is 
 * Composite A/S (Danish business reg.no. 21744409). All Rights Reserved
 * 
 * Section 11 of the License is EXPRESSLY amended to include a provision stating 
 * that any dispute, including but not limited to disputes related to the enforcement 
 * of the License, to which Composite A/S as owner of the Original Code, as Initial 
 * Developer or in any other role, becomes a part to shall be governed by Danish law 
 * and be initiated before the Copenhagen City Court ("K�benhavns Byret")            
 */

using System;
using System.IO;
using System.Text;
using Composite.Core.Logging;
using System.Collections.Generic;


namespace Composite.Core.IO
{
    /// <summary>    
    /// </summary>
    /// <exclude />
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 
    public static class DirectoryUtils
    {
        /// <summary>
        /// Ensures that the directories in the path exists and if they dont they will be created
        /// </summary>
        public static void EnsurePath(string filePath)
        {
            string directory = Path.GetDirectoryName(filePath);

            EnsureDirectoryExists(directory);
        }

        /// <summary>
        /// Ensures that the directory exists 
        /// </summary>
        public static void EnsureDirectoryExists(string directory)
        {
            string[] directories = directory.Split(Path.DirectorySeparatorChar);

            if (directories.Length == 2) return;

            string currentPath = string.Format("{0}{1}", directories[0], Path.DirectorySeparatorChar);

            for (int i = 1; i < directories.Length; ++i)
            {
                currentPath = string.Format("{0}{1}{2}", currentPath, directories[i], Path.DirectorySeparatorChar);

                if (currentPath.StartsWith(PathUtil.BaseDirectory, StringComparison.InvariantCultureIgnoreCase)) // don't touch dirs outside our own folder!
                {
                    if (C1Directory.Exists(currentPath) == false)
                    {
                        C1Directory.CreateDirectory(currentPath);
                    }
                }
            }
        }


        /// <summary>
        /// Delete a file. If the deleteEmptyDirectoresRecursively is true all empty directories
        /// from buttom up are also deleted.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="deleteEmptyDirectoresRecursively"></param>
        public static void DeleteFile(string path, bool deleteEmptyDirectoresRecursively)
        {
            LoggingService.LogVerbose("DirectoryUtil", string.Format("Deleting file '{0}'", path));
            C1File.Delete(path);

            if (deleteEmptyDirectoresRecursively)
            {
                string directory = Path.GetDirectoryName(path);

                string[] directories = directory.Split(Path.DirectorySeparatorChar);

                for (int i = directories.Length; i > 1; --i)
                {
                    StringBuilder stringBuilder = new StringBuilder();

                    for (int j = 0; j < i; ++j)
                    {
                        stringBuilder.Append(directories[j]);
                        stringBuilder.Append(Path.DirectorySeparatorChar);
                    }

                    string currentPath = stringBuilder.ToString();
                    if (C1Directory.GetFiles(currentPath).Length == 0)
                    {
                        LoggingService.LogVerbose("DirectoryUtil", string.Format("Deleting directory '{0}'", currentPath));
                        C1Directory.Delete(currentPath);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }



        /// <summary>
        /// Deletes all files recursively leaving all sub directories.
        /// </summary>
        /// <param name="directoryPath"></param>
        public static void DeleteFilesRecursively(string directoryPath)
        {
            foreach (string file in C1Directory.GetFiles(directoryPath))
            {
                C1File.Delete(file);
            }

            foreach (string directory in C1Directory.GetDirectories(directoryPath))
            {
                DeleteFilesRecursively(directory);
            }
        }



        /// <exclude />
        public static void RemoveReadOnlyRecursively(string directoryPath)
        {
            foreach (string file in C1Directory.GetFiles(directoryPath))
            {
                FileUtils.RemoveReadOnly(file);
            }


            foreach (string directory in C1Directory.GetDirectories(directoryPath))
            {
                RemoveReadOnlyRecursively(directory);
            }
        }



        /// <exclude />
        public static IEnumerable<string> GetFilesRecursively(string path)
        {
            foreach (string filePath in Directory.GetFiles(path))
            {
                yield return filePath;
            }

            foreach (string subPath in Directory.GetDirectories(path))
            {
                foreach (string filePath in GetFilesRecursively(subPath))
                {
                    yield return filePath;
                }
            }
        }
    }
}
